From 983fcb500e57e08bdd0331c285787b0425417cd1 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 20 Apr 2005 10:39:58 +0000 Subject: [PATCH] bitkeeper revision 1.1338 (4266317ezHysqYzH_WRvfueqwU4i4Q) Grant tables for FreeBSD. Signed-off-by: Kip Macy Signed-off-by: Keir Fraser --- .rootkeys | 2 + freebsd-5.3-xen-sparse/conf/files.i386-xen | 11 +- .../i386-xen/i386-xen/gnttab.c | 367 ++++++++++++++++++ .../i386-xen/i386-xen/machdep.c | 3 +- .../i386-xen/i386-xen/pmap.c | 22 +- .../i386-xen/include/gnttab.h | 71 ++++ .../i386-xen/include/hypervisor-ifs.h | 2 + .../i386-xen/include/hypervisor.h | 116 ++++-- .../i386-xen/include/xenpmap.h | 25 +- .../i386-xen/xen/blkfront/xb_blkfront.c | 96 ++++- 10 files changed, 657 insertions(+), 58 deletions(-) create mode 100644 freebsd-5.3-xen-sparse/i386-xen/i386-xen/gnttab.c create mode 100644 freebsd-5.3-xen-sparse/i386-xen/include/gnttab.h diff --git a/.rootkeys b/.rootkeys index c463985a86..537470ff4b 100644 --- a/.rootkeys +++ b/.rootkeys @@ -71,6 +71,7 @@ 423e7e88B5vxFblc-MlhxKk9e4ieBw freebsd-5.3-xen-sparse/i386-xen/i386-xen/evtchn.c 423e7e88z_BrFu1O71-Ya4pXJpjAPQ freebsd-5.3-xen-sparse/i386-xen/i386-xen/exception.s 423e7e88uDvAZLmABMkqOpmemyVRyw freebsd-5.3-xen-sparse/i386-xen/i386-xen/genassym.c +4266317eeOLpvRxIjmOYQVlL4WWQsg freebsd-5.3-xen-sparse/i386-xen/i386-xen/gnttab.c 423e7e88yr5NFQudubMnkvdb_y-Gtg freebsd-5.3-xen-sparse/i386-xen/i386-xen/hypervisor.c 423e7e88Y-e-4RRf9nrgkVn5PXUv3Q freebsd-5.3-xen-sparse/i386-xen/i386-xen/i686_mem.c 423e7e88b8m2cuGtOxVvs4Sok4Vk7Q freebsd-5.3-xen-sparse/i386-xen/i386-xen/initcpu.c @@ -95,6 +96,7 @@ 423e7e8avrrUxDugrwq_GJp499DkJw freebsd-5.3-xen-sparse/i386-xen/include/ctrl_if.h 423e7e8apY1r9Td-S0eZITNZZbfNTQ freebsd-5.3-xen-sparse/i386-xen/include/evtchn.h 423e7e8aL9DsObEegCwtILrF6SWcAQ freebsd-5.3-xen-sparse/i386-xen/include/frame.h +4266317eOVvN00XdcqRfDRFIrbqgvg freebsd-5.3-xen-sparse/i386-xen/include/gnttab.h 423e7e8btv8Gojq50ggnP5A1Dkc4kA freebsd-5.3-xen-sparse/i386-xen/include/hypervisor-ifs.h 423e7e8buhTLVFLZ33-5s8-UdADSZg freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h 423e7e8bnHT1kMD-FPC7zHZR7l3VXw freebsd-5.3-xen-sparse/i386-xen/include/md_var.h diff --git a/freebsd-5.3-xen-sparse/conf/files.i386-xen b/freebsd-5.3-xen-sparse/conf/files.i386-xen index 189378d469..0c6aea90a2 100644 --- a/freebsd-5.3-xen-sparse/conf/files.i386-xen +++ b/freebsd-5.3-xen-sparse/conf/files.i386-xen @@ -202,18 +202,19 @@ i386/i386/perfmon.c optional perfmon profiling-routine i386-xen/i386-xen/pmap.c standard i386-xen/i386-xen/support.s standard i386-xen/i386-xen/swtch.s standard -i386-xen/i386-xen/sys_machdep.c standard +i386-xen/i386-xen/sys_machdep.c standard i386-xen/i386-xen/trap.c standard i386/i386/tsc.c standard -i386-xen/i386-xen/vm_machdep.c standard +i386-xen/i386-xen/vm_machdep.c standard i386-xen/i386-xen/clock.c standard # xen specific arch-dep files i386-xen/i386-xen/hypervisor.c standard i386-xen/i386-xen/xen_machdep.c standard -i386-xen/i386-xen/xen_bus.c standard -i386-xen/i386-xen/evtchn.c standard -i386-xen/i386-xen/ctrl_if.c standard +i386-xen/i386-xen/xen_bus.c standard +i386-xen/i386-xen/evtchn.c standard +i386-xen/i386-xen/ctrl_if.c standard +i386-xen/i386-xen/gnttab.c standard i386/isa/asc.c count asc diff --git a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/gnttab.c b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/gnttab.c new file mode 100644 index 0000000000..97ff0d129d --- /dev/null +++ b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/gnttab.c @@ -0,0 +1,367 @@ +/****************************************************************************** + * gnttab.c + * + * Two sets of functionality: + * 1. Granting foreign access to our memory reservation. + * 2. Accessing others' memory reservations via grant references. + * (i.e., mechanisms for both sender and recipient of grant references) + * + * Copyright (c) 2005, Christopher Clark + * Copyright (c) 2004, K A Fraser + */ + +#include "opt_pmap.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c)) + + +/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ +static inline void rep_nop(void) +{ + __asm__ __volatile__ ( "rep;nop" : : : "memory" ); +} +#define cpu_relax() rep_nop() + +#if 1 +#define ASSERT(_p) \ + if ( !(_p) ) { printk("Assertion '%s': line %d, file %s\n", \ + #_p , __LINE__, __FILE__); *(int*)0=0; } +#else +#define ASSERT(_p) ((void)0) +#endif + +#define WPRINTK(fmt, args...) \ + printk("xen_grant: " fmt, ##args) + +static grant_ref_t gnttab_free_list[NR_GRANT_ENTRIES]; +static grant_ref_t gnttab_free_head; + +static grant_entry_t *shared; +#if 0 +/* /proc/xen/grant */ +static struct proc_dir_entry *grant_pde; +#endif + +/* + * Lock-free grant-entry allocator + */ + +static inline int +get_free_entry(void) +{ + grant_ref_t fh, nfh = gnttab_free_head; + do { if ( unlikely((fh = nfh) == NR_GRANT_ENTRIES) ) return -1; } + while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, + gnttab_free_list[fh])) != fh) ); + return fh; +} + +static inline void +put_free_entry(grant_ref_t ref) +{ + grant_ref_t fh, nfh = gnttab_free_head; + do { gnttab_free_list[ref] = fh = nfh; wmb(); } + while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) ); +} + +/* + * Public grant-issuing interface functions + */ + +int +gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly) +{ + int ref; + + if ( unlikely((ref = get_free_entry()) == -1) ) + return -ENOSPC; + + shared[ref].frame = frame; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); + + return ref; +} + +void +gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, + unsigned long frame, int readonly) +{ + shared[ref].frame = frame; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); +} + + +int +gnttab_query_foreign_access(grant_ref_t ref) +{ + uint16_t nflags; + + nflags = shared[ref].flags; + + return (nflags & (GTF_reading|GTF_writing)); +} + +void +gnttab_end_foreign_access(grant_ref_t ref, int readonly) +{ + uint16_t flags, nflags; + + nflags = shared[ref].flags; + do { + if ( (flags = nflags) & (GTF_reading|GTF_writing) ) + printk("WARNING: g.e. still in use!\n"); + } + while ( (nflags = cmpxchg(&shared[ref].flags, flags, 0)) != flags ); + + put_free_entry(ref); +} + +int +gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn) +{ + int ref; + + if ( unlikely((ref = get_free_entry()) == -1) ) + return -ENOSPC; + + shared[ref].frame = pfn; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_accept_transfer; + + return ref; +} + +void +gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid, + unsigned long pfn) +{ + shared[ref].frame = pfn; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_accept_transfer; +} + +unsigned long +gnttab_end_foreign_transfer(grant_ref_t ref) +{ + unsigned long frame = 0; + uint16_t flags; + + flags = shared[ref].flags; + ASSERT(flags == (GTF_accept_transfer | GTF_transfer_committed)); + + /* + * If a transfer is committed then wait for the frame address to appear. + * Otherwise invalidate the grant entry against future use. + */ + if ( likely(flags != GTF_accept_transfer) || + (cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) ) + while ( unlikely((frame = shared[ref].frame) == 0) ) + cpu_relax(); + + put_free_entry(ref); + + return frame; +} + +void +gnttab_free_grant_references(uint16_t count, grant_ref_t head) +{ + /* TODO: O(N)...? */ + grant_ref_t to_die = 0, next = head; + int i; + + for ( i = 0; i < count; i++ ) + to_die = next; + next = gnttab_free_list[next]; + put_free_entry( to_die ); +} + +int +gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head, + grant_ref_t *terminal) +{ + int i; + grant_ref_t h = gnttab_free_head; + + for ( i = 0; i < count; i++ ) + if ( unlikely(get_free_entry() == -1) ) + goto not_enough_refs; + + *head = h; + *terminal = gnttab_free_head; + + return 0; + +not_enough_refs: + gnttab_free_head = h; + return -ENOSPC; +} + +int +gnttab_claim_grant_reference(grant_ref_t *private_head, grant_ref_t terminal ) +{ + grant_ref_t g; + if ( unlikely((g = *private_head) == terminal) ) + return -ENOSPC; + *private_head = gnttab_free_list[g]; + return g; +} + +void +gnttab_release_grant_reference( grant_ref_t *private_head, + grant_ref_t release ) +{ + gnttab_free_list[release] = *private_head; + *private_head = release; +} +#ifdef notyet +static int +grant_ioctl(struct cdev *dev, u_long cmd, caddr_t data, + int flag, struct thread *td) +{ + + int ret; + privcmd_hypercall_t hypercall; + + /* XXX Need safety checks here if using for anything other + * than debugging */ + return -ENOSYS; + + if ( cmd != IOCTL_PRIVCMD_HYPERCALL ) + return -ENOSYS; + + if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) ) + return -EFAULT; + + if ( hypercall.op != __HYPERVISOR_grant_table_op ) + return -ENOSYS; + + /* hypercall-invoking asm taken from privcmd.c */ + __asm__ __volatile__ ( + "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; " + "movl 4(%%eax),%%ebx ;" + "movl 8(%%eax),%%ecx ;" + "movl 12(%%eax),%%edx ;" + "movl 16(%%eax),%%esi ;" + "movl 20(%%eax),%%edi ;" + "movl (%%eax),%%eax ;" + TRAP_INSTR "; " + "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" + : "=a" (ret) : "0" (&hypercall) : "memory" ); + + return ret; + +} + +static struct cdevsw gnttab_cdevsw = { + d_ioctl: grant_ioctl, +}; + +static int +grant_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + unsigned int i; + grant_entry_t *gt; + + gt = (grant_entry_t *)shared; + len = 0; + + for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) + /* TODO: safety catch here until this can handle >PAGE_SIZE output */ + if (len > (PAGE_SIZE - 200)) + { + len += sprintf( page + len, "Truncated.\n"); + break; + } + + if ( gt[i].flags ) + len += sprintf( page + len, + "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n", + i, + gt[i].flags, + gt[i].domid, + gt[i].frame ); + + *eof = 1; + return len; +} + +static int +grant_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + /* TODO: implement this */ + return -ENOSYS; +} +#endif +static int +gnttab_init(void *unused) +{ + gnttab_setup_table_t setup; + unsigned long frames[NR_GRANT_FRAMES]; + int i; + + setup.dom = DOMID_SELF; + setup.nr_frames = NR_GRANT_FRAMES; + setup.frame_list = frames; + + if (HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0) + panic("grant table setup failed\n"); + if (setup.status != 0) + panic("non-zero status in grant table setup\n"); + shared = (grant_entry_t *)kmem_alloc_nofault(kernel_map, NR_GRANT_FRAMES); + + for (i = 0; i < NR_GRANT_FRAMES; i++) + pmap_kenter_ma((vm_offset_t)(shared + (i*PAGE_SIZE)), frames[i] << PAGE_SHIFT); + + for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) + gnttab_free_list[i] = i + 1; +#if 0 + /* + * /proc/xen/grant : used by libxc to access grant tables + */ + if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL ) + { + WPRINTK("Unable to create grant xen proc entry\n"); + return -1; + } + + grant_file_ops.read = grant_pde->proc_fops->read; + grant_file_ops.write = grant_pde->proc_fops->write; + + grant_pde->proc_fops = &grant_file_ops; + + grant_pde->read_proc = &grant_read; + grant_pde->write_proc = &grant_write; +#endif + printk("Grant table initialized\n"); + return 0; +} + +SYSINIT(gnttab, SI_SUB_PSEUDO, SI_ORDER_FIRST, gnttab_init, NULL); diff --git a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/machdep.c b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/machdep.c index 0d18e7d4c0..f954962f1e 100644 --- a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/machdep.c +++ b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/machdep.c @@ -1387,6 +1387,7 @@ initvalues(start_info_t *startinfo) { int i; #ifdef WRITABLE_PAGETABLES + XENPRINTF("using writable pagetables\n"); HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); #endif @@ -1457,7 +1458,7 @@ initvalues(start_info_t *startinfo) /* allocate remainder of NKPT pages */ for (i = 0; i < NKPT-1; i++, tmpindex++) - PT_SET_VA(((unsigned long *)startinfo->pt_base) + KPTDI + i + 1, (tmpindex << PAGE_SHIFT)| PG_M | PG_RW | PG_V | PG_A, TRUE); + PD_SET_VA(((unsigned long *)startinfo->pt_base) + KPTDI + i + 1, (tmpindex << PAGE_SHIFT)| PG_M | PG_RW | PG_V | PG_A, TRUE); tmpindex += NKPT-1; PT_UPDATES_FLUSH(); diff --git a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/pmap.c b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/pmap.c index 89705be1af..a9e536f41c 100644 --- a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/pmap.c +++ b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/pmap.c @@ -381,9 +381,10 @@ pmap_bootstrap(firstaddr, loadaddr) * CMAP1/CMAP2 are used for zeroing and copying pages. * CMAP3 is used for the idle process page zeroing. */ - SYSMAP(caddr_t, CMAP1, CADDR1, 1) - SYSMAP(caddr_t, CMAP2, CADDR2, 1) - SYSMAP(caddr_t, CMAP3, CADDR3, 1) + SYSMAP(caddr_t, CMAP1, CADDR1, 1); + SYSMAP(caddr_t, CMAP2, CADDR2, 1); + SYSMAP(caddr_t, CMAP3, CADDR3, 1); + PT_CLEAR_VA(CMAP3, TRUE); mtx_init(&CMAPCADDR12_lock, "CMAPCADDR12", NULL, MTX_DEF); @@ -416,7 +417,7 @@ pmap_bootstrap(firstaddr, loadaddr) PT_CLEAR_VA(CMAP2, FALSE); for (i = 0; i < NKPT; i++) - PT_CLEAR_VA(&PTD[i], FALSE); + PD_CLEAR_VA(&PTD[i], FALSE); PT_UPDATES_FLUSH(); #ifdef XEN_UNNEEDED /* Turn on PG_G on kernel page(s) */ @@ -961,6 +962,19 @@ pmap_kenter(vm_offset_t va, vm_paddr_t pa) pte_store(pte, pa | PG_RW | PG_V | pgeflag); } +/* + * Add a wired page to the kva. + * Note: not SMP coherent. + */ +PMAP_INLINE void +pmap_kenter_ma(vm_offset_t va, vm_paddr_t ma) +{ + pt_entry_t *pte; + + pte = vtopte(va); + PT_SET_VA_MA(pte, ma | PG_RW | PG_V | pgeflag, TRUE); +} + /* * Remove a page from the kernel pagetables. * Note: not SMP coherent. diff --git a/freebsd-5.3-xen-sparse/i386-xen/include/gnttab.h b/freebsd-5.3-xen-sparse/i386-xen/include/gnttab.h new file mode 100644 index 0000000000..76733a0400 --- /dev/null +++ b/freebsd-5.3-xen-sparse/i386-xen/include/gnttab.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * gnttab.h + * + * Two sets of functionality: + * 1. Granting foreign access to our memory reservation. + * 2. Accessing others' memory reservations via grant references. + * (i.e., mechanisms for both sender and recipient of grant references) + * + * Copyright (c) 2004, K A Fraser + * Copyright (c) 2005, Christopher Clark + */ + +#ifndef __ASM_GNTTAB_H__ +#define __ASM_GNTTAB_H__ + +#include +#include + +/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ +#define NR_GRANT_FRAMES 4 +#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) + +int +gnttab_grant_foreign_access( + domid_t domid, unsigned long frame, int readonly); + +void +gnttab_end_foreign_access( + grant_ref_t ref, int readonly); + +int +gnttab_grant_foreign_transfer( + domid_t domid, unsigned long pfn); + +unsigned long +gnttab_end_foreign_transfer( + grant_ref_t ref); + +int +gnttab_query_foreign_access( + grant_ref_t ref ); + +/* + * operations on reserved batches of grant references + */ +int +gnttab_alloc_grant_references( + uint16_t count, grant_ref_t *pprivate_head, grant_ref_t *private_terminal ); + +void +gnttab_free_grant_references( + uint16_t count, grant_ref_t private_head ); + +int +gnttab_claim_grant_reference( grant_ref_t *pprivate_head, grant_ref_t terminal +); + +void +gnttab_release_grant_reference( + grant_ref_t *private_head, grant_ref_t release ); + +void +gnttab_grant_foreign_access_ref( + grant_ref_t ref, domid_t domid, unsigned long frame, int readonly); + +void +gnttab_grant_foreign_transfer_ref( + grant_ref_t, domid_t domid, unsigned long pfn); + + +#endif /* __ASM_GNTTAB_H__ */ diff --git a/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor-ifs.h b/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor-ifs.h index 4f75d27a9a..a77ee4a6be 100644 --- a/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor-ifs.h +++ b/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor-ifs.h @@ -11,6 +11,7 @@ #define u32 uint32_t #define u64 uint64_t +#define CONFIG_XEN_BLKDEV_GRANT #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #undef blkif_sector_t /* XXX pre-processor didn't do the */ #define blkif_sector_t uint64_t /* right thing */ diff --git a/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h b/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h index cfae321129..c93727d904 100644 --- a/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h +++ b/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h @@ -38,7 +38,8 @@ typedef struct { unsigned long pte_low, pte_high; } pte_t; * Assembler stubs for hyper-calls. */ -static inline int HYPERVISOR_set_trap_table(trap_info_t *table) +static inline int +HYPERVISOR_set_trap_table(trap_info_t *table) { int ret; __asm__ __volatile__ ( @@ -83,7 +84,8 @@ HYPERVISOR_mmuext_op( -static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries) +static inline int +HYPERVISOR_set_gdt(unsigned long *frame_list, int entries) { int ret; __asm__ __volatile__ ( @@ -95,7 +97,8 @@ static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries) return ret; } -static inline int HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp) +static inline int +HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp) { int ret; __asm__ __volatile__ ( @@ -106,7 +109,8 @@ static inline int HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp) return ret; } -static inline int HYPERVISOR_set_callbacks( +static inline int +HYPERVISOR_set_callbacks( unsigned long event_selector, unsigned long event_address, unsigned long failsafe_selector, unsigned long failsafe_address) { @@ -120,7 +124,8 @@ static inline int HYPERVISOR_set_callbacks( return ret; } -static inline int HYPERVISOR_fpu_taskswitch(void) +static inline int +HYPERVISOR_fpu_taskswitch(void) { int ret; __asm__ __volatile__ ( @@ -130,7 +135,8 @@ static inline int HYPERVISOR_fpu_taskswitch(void) return ret; } -static inline int HYPERVISOR_yield(void) +static inline int +HYPERVISOR_yield(void) { int ret; __asm__ __volatile__ ( @@ -141,7 +147,8 @@ static inline int HYPERVISOR_yield(void) return ret; } -static inline int HYPERVISOR_block(void) +static inline int +HYPERVISOR_block(void) { int ret; __asm__ __volatile__ ( @@ -152,7 +159,8 @@ static inline int HYPERVISOR_block(void) return ret; } -static inline int HYPERVISOR_shutdown(void) +static inline int +HYPERVISOR_shutdown(void) { int ret; __asm__ __volatile__ ( @@ -164,7 +172,8 @@ static inline int HYPERVISOR_shutdown(void) return ret; } -static inline int HYPERVISOR_reboot(void) +static inline int +HYPERVISOR_reboot(void) { int ret; __asm__ __volatile__ ( @@ -176,7 +185,8 @@ static inline int HYPERVISOR_reboot(void) return ret; } -static inline int HYPERVISOR_suspend(unsigned long srec) +static inline int +HYPERVISOR_suspend(unsigned long srec) { int ret; /* NB. On suspend, control software expects a suspend record in %esi. */ @@ -189,7 +199,8 @@ static inline int HYPERVISOR_suspend(unsigned long srec) return ret; } -static inline long HYPERVISOR_set_timer_op(uint64_t timeout) +static inline long +HYPERVISOR_set_timer_op(uint64_t timeout) { int ret; unsigned long timeout_hi = (unsigned long)(timeout>>32); @@ -202,7 +213,8 @@ static inline long HYPERVISOR_set_timer_op(uint64_t timeout) return ret; } -static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op) +static inline int +HYPERVISOR_dom0_op(dom0_op_t *dom0_op) { int ret; dom0_op->interface_version = DOM0_INTERFACE_VERSION; @@ -214,7 +226,8 @@ static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op) return ret; } -static inline int HYPERVISOR_set_debugreg(int reg, unsigned long value) +static inline int +HYPERVISOR_set_debugreg(int reg, unsigned long value) { int ret; __asm__ __volatile__ ( @@ -225,7 +238,8 @@ static inline int HYPERVISOR_set_debugreg(int reg, unsigned long value) return ret; } -static inline unsigned long HYPERVISOR_get_debugreg(int reg) +static inline unsigned long +HYPERVISOR_get_debugreg(int reg) { unsigned long ret; __asm__ __volatile__ ( @@ -236,7 +250,8 @@ static inline unsigned long HYPERVISOR_get_debugreg(int reg) return ret; } -static inline int HYPERVISOR_update_descriptor( +static inline int +HYPERVISOR_update_descriptor( unsigned long pa, unsigned long word1, unsigned long word2) { int ret; @@ -248,7 +263,8 @@ static inline int HYPERVISOR_update_descriptor( return ret; } -static inline int HYPERVISOR_set_fast_trap(int idx) +static inline int +HYPERVISOR_set_fast_trap(int idx) { int ret; __asm__ __volatile__ ( @@ -259,9 +275,10 @@ static inline int HYPERVISOR_set_fast_trap(int idx) return ret; } -static inline int HYPERVISOR_dom_mem_op(unsigned int op, - unsigned long *pages, - unsigned long nr_pages) +static inline int +HYPERVISOR_dom_mem_op(unsigned int op, + unsigned long *pages, + unsigned long nr_pages) { int ret; __asm__ __volatile__ ( @@ -271,7 +288,8 @@ static inline int HYPERVISOR_dom_mem_op(unsigned int op, return ret; } -static inline int HYPERVISOR_multicall(void *call_list, int nr_calls) +static inline int +HYPERVISOR_multicall(void *call_list, int nr_calls) { int ret; __asm__ __volatile__ ( @@ -282,7 +300,8 @@ static inline int HYPERVISOR_multicall(void *call_list, int nr_calls) return ret; } -static inline int HYPERVISOR_update_va_mapping( +static inline int +HYPERVISOR_update_va_mapping( unsigned long page_nr, unsigned long new_val, unsigned long flags) { int ret; @@ -300,7 +319,8 @@ static inline int HYPERVISOR_update_va_mapping( return ret; } -static inline int HYPERVISOR_event_channel_op(void *op) +static inline int +HYPERVISOR_event_channel_op(void *op) { int ret; __asm__ __volatile__ ( @@ -311,7 +331,8 @@ static inline int HYPERVISOR_event_channel_op(void *op) return ret; } -static inline int HYPERVISOR_xen_version(int cmd) +static inline int +HYPERVISOR_xen_version(int cmd) { int ret; __asm__ __volatile__ ( @@ -322,7 +343,8 @@ static inline int HYPERVISOR_xen_version(int cmd) return ret; } -static inline int HYPERVISOR_console_io(int cmd, int count, char *str) +static inline int +HYPERVISOR_console_io(int cmd, int count, char *str) { int ret; __asm__ __volatile__ ( @@ -333,36 +355,62 @@ static inline int HYPERVISOR_console_io(int cmd, int count, char *str) return ret; } -static __inline int HYPERVISOR_console_write(char *str, int count) +static inline int +HYPERVISOR_console_write(char *str, int count) { return HYPERVISOR_console_io(CONSOLEIO_write, count, str); } -static inline int HYPERVISOR_physdev_op(void *physdev_op) +static inline int +HYPERVISOR_physdev_op(void *physdev_op) { int ret; + unsigned long ign; + __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_physdev_op), - "b" (physdev_op) : "memory" ); + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op) + : "memory" ); return ret; } -static inline int HYPERVISOR_update_va_mapping_otherdomain( - unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid) +static inline int +HYPERVISOR_grant_table_op( + unsigned int cmd, void *uop, unsigned int count) { int ret; + unsigned long ign1, ign2, ign3; + __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_update_va_mapping_otherdomain), - "b" (page_nr), "c" ((new_val).pte_low), "d" (flags), "S" (domid) : + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) + : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count) + : "memory" ); + + return ret; +} + +static inline int +HYPERVISOR_update_va_mapping_otherdomain( + unsigned long va, pte_t new_val, unsigned long flags, domid_t domid) +{ + int ret; + unsigned long ign1, ign2, ign3, ign4; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) + : "0" (__HYPERVISOR_update_va_mapping_otherdomain), + "1" (va), "2" ((new_val).pte_low), "3" (flags), "4" (domid) : "memory" ); - + return ret; } -static inline int HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type) +static inline int +HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type) { int ret; __asm__ __volatile__ ( diff --git a/freebsd-5.3-xen-sparse/i386-xen/include/xenpmap.h b/freebsd-5.3-xen-sparse/i386-xen/include/xenpmap.h index 2149d5dc48..c0fa939241 100644 --- a/freebsd-5.3-xen-sparse/i386-xen/include/xenpmap.h +++ b/freebsd-5.3-xen-sparse/i386-xen/include/xenpmap.h @@ -60,6 +60,14 @@ void pmap_ref(pt_entry_t *pte, unsigned long ma); #endif #define ALWAYS_SYNC 0 +#define PT_DEBUG + +#ifdef PT_DEBUG +#define PT_LOG() printk("WP PT_SET %s:%d\n", __FILE__, __LINE__) +#else +#define PT_LOG() +#endif + #define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */ #define PT_GET(_ptp) \ @@ -68,15 +76,18 @@ void pmap_ref(pt_entry_t *pte, unsigned long ma); #ifdef WRITABLE_PAGETABLES #define PT_SET_VA(_ptp,_npte,sync) do { \ PMAP_REF((_ptp), xpmap_ptom(_npte)); \ - *(_ptp) = xpmap_ptom((_npte)); \ + PT_LOG(); \ + *(_ptp) = xpmap_ptom((_npte)); \ } while (/*CONSTCOND*/0) -#define PT_SET_VA_MA(_ptp,_npte,sync) do { \ +#define PT_SET_VA_MA(_ptp,_npte,sync) do { \ PMAP_REF((_ptp), (_npte)); \ - *(_ptp) = (_npte); \ + PT_LOG(); \ + *(_ptp) = (_npte); \ } while (/*CONSTCOND*/0) #define PT_CLEAR_VA(_ptp, sync) do { \ PMAP_REF((pt_entry_t *)(_ptp), 0); \ - *(_ptp) = 0; \ + PT_LOG(); \ + *(_ptp) = 0; \ } while (/*CONSTCOND*/0) #define PD_SET_VA(_ptp,_npte,sync) do { \ @@ -85,7 +96,7 @@ void pmap_ref(pt_entry_t *pte, unsigned long ma); xpmap_ptom((_npte))); \ if (sync || ALWAYS_SYNC) xen_flush_queue(); \ } while (/*CONSTCOND*/0) -#define PD_SET_VA_MA(_ptp,_npte,sync) do { \ +#define PD_SET_VA_MA(_ptp,_npte,sync) do { \ PMAP_REF((_ptp), (_npte)); \ xen_queue_pt_update((pt_entry_t *)vtomach((_ptp)), (_npte)); \ if (sync || ALWAYS_SYNC) xen_flush_queue(); \ @@ -105,9 +116,9 @@ void pmap_ref(pt_entry_t *pte, unsigned long ma); xpmap_ptom(_npte)); \ if (sync || ALWAYS_SYNC) xen_flush_queue(); \ } while (/*CONSTCOND*/0) -#define PT_SET_VA_MA(_ptp,_npte,sync) do { \ +#define PT_SET_VA_MA(_ptp,_npte,sync) do { \ PMAP_REF((_ptp), (_npte)); \ - xen_queue_pt_update((pt_entry_t *)vtomach(_ptp), _npte); \ + xen_queue_pt_update((pt_entry_t *)vtomach(_ptp), _npte);\ if (sync || ALWAYS_SYNC) xen_flush_queue(); \ } while (/*CONSTCOND*/0) #define PT_CLEAR_VA(_ptp, sync) do { \ diff --git a/freebsd-5.3-xen-sparse/i386-xen/xen/blkfront/xb_blkfront.c b/freebsd-5.3-xen-sparse/i386-xen/xen/blkfront/xb_blkfront.c index a9e9b2cad1..5aeb212153 100644 --- a/freebsd-5.3-xen-sparse/i386-xen/xen/blkfront/xb_blkfront.c +++ b/freebsd-5.3-xen-sparse/i386-xen/xen/blkfront/xb_blkfront.c @@ -46,12 +46,19 @@ #include #include + + +#ifdef CONFIG_XEN_BLKDEV_GRANT +#include +#endif + /* prototypes */ struct xb_softc; static void xb_startio(struct xb_softc *sc); static void xb_vbdinit(void); static void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp); static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id); +static void blkif_control_probe_send(blkif_request_t *req, blkif_response_t *rsp, unsigned long address); struct xb_softc { device_t xb_dev; @@ -104,6 +111,14 @@ static blkif_front_ring_t blk_ring; #define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) +#ifdef CONFIG_XEN_BLKDEV_GRANT +static domid_t rdomid = 0; +static grant_ref_t gref_head, gref_terminal; +#define MAXIMUM_OUTSTANDING_BLOCK_REQS \ + (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE) +#endif + + static unsigned long rec_ring_free; blkif_request_t rec_ring[BLK_RING_SIZE]; @@ -151,8 +166,9 @@ ADD_ID_TO_FREELIST( unsigned long id ) rec_ring_free = id; } -static inline void translate_req_to_pfn(blkif_request_t *xreq, - blkif_request_t *req) +static inline void +translate_req_to_pfn(blkif_request_t *xreq, + blkif_request_t *req) { int i; @@ -163,7 +179,11 @@ static inline void translate_req_to_pfn(blkif_request_t *xreq, xreq->sector_number = req->sector_number; for ( i = 0; i < req->nr_segments; i++ ){ +#ifdef CONFIG_XEN_BLKDEV_GRANT + xreq->frame_and_sects[i] = req->frame_and_sects[i]; +#else xreq->frame_and_sects[i] = xpmap_mtop(req->frame_and_sects[i]); +#endif } } @@ -179,7 +199,11 @@ static inline void translate_req_to_mfn(blkif_request_t *xreq, xreq->sector_number = req->sector_number; for ( i = 0; i < req->nr_segments; i++ ){ +#ifdef CONFIG_XEN_BLKDEV_GRANT + xreq->frame_and_sects[i] = req->frame_and_sects[i]; +#else xreq->frame_and_sects[i] = xpmap_ptom(req->frame_and_sects[i]); +#endif } } @@ -340,6 +364,9 @@ xb_startio(struct xb_softc *sc) int s, queued = 0; unsigned long id; unsigned int fsect, lsect; +#ifdef CONFIG_XEN_BLKDEV_GRANT + int ref; +#endif if (unlikely(blkif_state != BLKIF_STATE_CONNECTED)) @@ -396,12 +423,26 @@ xb_startio(struct xb_softc *sc) req->nr_segments = 1; /* not doing scatter/gather since buffer * chaining is not supported. */ +#ifdef CONFIG_XEN_BLKDEV_GRANT + /* install a grant reference. */ + ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); + KASSERT( ref != -ENOSPC, ("grant_reference failed") ); + + gnttab_grant_foreign_access_ref( + ref, + rdomid, + buffer_ma >> PAGE_SHIFT, + req->operation & 1 ); /* ??? */ + + req->frame_and_sects[0] = + (((uint32_t) ref) << 16) | (fsect << 3) | lsect; +#else /* * upper bits represent the machine address of the buffer and the * lower bits is the number of sectors to be read/written. */ req->frame_and_sects[0] = buffer_ma | (fsect << 3) | lsect; - +#endif /* Keep a private copy so we can reissue requests when recovering. */ translate_req_to_pfn( &rec_ring[id], req); @@ -503,9 +544,14 @@ xb_vbdinit(void) memset(&req, 0, sizeof(req)); req.operation = BLKIF_OP_PROBE; req.nr_segments = 1; +#ifdef CONFIG_XEN_BLKDEV_GRANT + blkif_control_probe_send(&req, &rsp, + (unsigned long)(vtomach(buf))); + +#else req.frame_and_sects[0] = vtomach(buf) | 7; blkif_control_send(&req, &rsp); - +#endif if ( rsp.status <= 0 ) { printk("xb_identify: Could not identify disks (%d)\n", rsp.status); free(buf, M_DEVBUF); @@ -526,6 +572,22 @@ xb_vbdinit(void) /***************************** COMMON CODE *******************************/ +#ifdef CONFIG_XEN_BLKDEV_GRANT +static void +blkif_control_probe_send(blkif_request_t *req, blkif_response_t *rsp, + unsigned long address) +{ + int ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); + KASSERT( ref != -ENOSPC, ("couldn't get grant reference") ); + + gnttab_grant_foreign_access_ref( ref, rdomid, address >> PAGE_SHIFT, 0 ); + + req->frame_and_sects[0] = (((uint32_t) ref) << 16) | 7; + + blkif_control_send(req, rsp); +} +#endif + void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp) { @@ -713,6 +775,10 @@ blkif_connect(blkif_fe_interface_status_t *status) blkif_evtchn = status->evtchn; blkif_irq = bind_evtchn_to_irq(blkif_evtchn); +#ifdef CONFIG_XEN_BLKDEV_GRANT + rdomid = status->domid; +#endif + err = intr_add_handler("xbd", blkif_irq, (driver_intr_t *)xb_response_intr, NULL, @@ -875,6 +941,14 @@ xb_init(void *unused) printk("[XEN] Initialising virtual block device driver\n"); +#ifdef CONFIG_XEN_BLKDEV_GRANT + if ( 0 > gnttab_alloc_grant_references( MAXIMUM_OUTSTANDING_BLOCK_REQS, + &gref_head, &gref_terminal )) + return; + printk("Blkif frontend is using grant tables.\n"); +#endif + + rec_ring_free = 0; for (i = 0; i < BLK_RING_SIZE; i++) { rec_ring[i].id = i+1; @@ -899,13 +973,21 @@ blkdev_resume(void) } #endif -/* XXXXX THIS IS A TEMPORARY FUNCTION UNTIL WE GET GRANT TABLES */ - void blkif_completion(blkif_request_t *req) { int i; +#ifdef CONFIG_XEN_BLKDEV_GRANT + grant_ref_t gref; + + for ( i = 0; i < req->nr_segments; i++ ) + { + gref = blkif_gref_from_fas(req->frame_and_sects[i]); + gnttab_release_grant_reference(&gref_head, gref); + } +#else + /* This is a hack to get the dirty logging bits set */ switch ( req->operation ) { case BLKIF_OP_READ: @@ -917,7 +999,7 @@ blkif_completion(blkif_request_t *req) } break; } - +#endif } MTX_SYSINIT(ioreq, &blkif_io_lock, "BIO LOCK", MTX_SPIN | MTX_NOWITNESS); /* XXX how does one enroll a lock? */ SYSINIT(xbdev, SI_SUB_PSEUDO, SI_ORDER_ANY, xb_init, NULL) -- 2.30.2